Rust (tiny-http)でのPiping Server実装
#tiny-http-piping-server-rust #Piping_Server #Rust #tiny-http #Tokio #制作物
GitHubリポジトリ
Rustのtiny-httpを使った実装。
https://gh-card.dev/repos/nwtgck/tiny-http-piping-server-rust.svg https://github.com/nwtgck/tiny-http-piping-server-rust
なぜtiny-http?
まずRustのHyperで実装したものがすでにある:Rust実装でPiping Severの転送速度を1.7倍~1.8倍高速化 (Hyper)
低レベルなHTTPサーバーがHyperよりも書きやすそうだった。Hyperも低レベル用のライブラリではあるが、RustのHyperでNode.jsライクなハンドラーは0.10だと使えていた様子が理由で、レスポンスがRequest -> Responseのような関数になる必要があって、少なくともPiping Serverを実装するときには実装しづらい。REST APIはすぐにリクエストがあればレスポンスを返すだけ。だが、Piping Serverの場合は対応する送信者や受信者が来るのを待つ挙動になる。そのためハンドラが即時返すRequest -> Responseのような関数では扱いづらい。ソケットは本来双方向通信できるものだから、より低レベルに近づけるならNode.js標準のようなAPIが好ましいのかなと思っている。
対して、tiny-httpのリクエストハンドリングは、request.respond(response)のように書くことができ、好きなタイミングでresponseをやってきたリクエストに返すことができるAPIになっている。それとリクエストのacceptループ(?)をfor request in server.incoming_requests() {}のように書ける。つまり、リクエストを待ち受ける処理がシングルスレッド。ハンドラがfnとかにならない。ArcとかMutexとかもなしで、変数を他のリクエストと安全に共有しやすかった。
Hyperでどのように実装しているかの詳細はRust実装でPiping Severの転送速度を1.7倍~1.8倍高速化 (Hyper)。
Node.js(TypeScript) vs Hyper vs Tiny-http の転送速度の比較
https://youtu.be/QiWXDs-Gz4k
各種バージョン
TypeScript: v0.11.4
Rust (Hyper): v0.1.0
Rust (tiny-http): 1e1a6f554117b379f7bc02ed6bcde7b86f9f1c10
結果は、1秒あたりの速度はHyperが一番速かった。だいたい 1.6GB/秒ぐらい。
Rust (Hyper) > Node.js > tiny-http
(>の左がより速い)
Hyperのときだけファンがよく回るのでCPUとかも使い方も違うのだと思う。単純な転送速度だけではなくてメモリ使用率とかCPU使用率とかもちゃんと比較したいならすべきだと思う。
Tokioの力でHyper速いのかもしれない。速いみたいだし。
以下のランキングでもいろんなフレームワークがある中でtokio-minihttpが1位。
https://gyazo.com/c3ecf13597ce3be408007b7d95de6a4d
サーバーの動かし方
以下のREADMEのようにcargo runまたは、配布しているDockerイメージをdocker runしてもサーバーを立てることができる。
https://github.com/nwtgck/tiny-http-piping-server-rust#readme
対応していない機能
複数受信
Multipart
他にもTypeScript版の方はContent-TypeとかContent-Lengthをつけたり、プリフライトリクエスト周りとかの処理とか色々と見えにくい機能もあるので、そういう差はある。思うことはHyper版よりもtiny-http版のほうがそういった細かい機能も実装しやすそうである。また、Rust (Hyper) 版とTypeScript版のPiping Serverの違いでは問題だった、「途中でクライアントが接続を切ると、そのパスが使えなくなる」という問題はtiny-http版ではない。
Rust版Piping Serverの今後
開発の活発さやライブラリユーザーの多さや転送速度を考えるとHyperの方が良さそうなことが分かった。ただ、TypeScript(Node.js)のPiping Serverと同等の機能を揃えるにはtiny-httpの方が実装しやすく、保守もしやすい気がする。Rust標準で低レベルなHTTPサーバーを書くライブラリが出てくれると嬉しいなと思っている。
関連:Rustに標準のHTTPライブラリないけど、2015年時点での議論